//
//  SymbolResultGenerator.m
//  LinkMap
//
//  Created by aron on 2022/5/7.
//  Copyright © 2022 ND. All rights reserved.
//

#import "SymbolResultGenerator.h"
#import "ObjectResult.h"
#import "SymbolUtils.h"

@implementation SymbolResultGenerator

- (NSString *)buildResultWithSymbols:(NSArray *)symbols searchKey:(NSString *)searchKey {
    NSMutableString *result = [@"文件大小\t文件名称\r\n\r\n" mutableCopy];
    NSUInteger totalSize = 0;
        
    for(ObjectResult *symbol in symbols) {
        if (searchKey.length > 0) {
            if ([symbol.file containsString:searchKey]) {
                [self appendResultWithSymbol:symbol result:result];
                totalSize += symbol.size;
            }
        } else {
            [self appendResultWithSymbol:symbol result:result];
            totalSize += symbol.size;
        }
    }
    
    [result appendFormat:@"\r\n总大小: %.2fM\r\n",(totalSize/1024.0/1024.0)];
    return result;
}

- (NSString *)buildCombinationResultWithSymbols:(NSArray *)symbols searchKey:(NSString *)searchKey {
    NSMutableString *result = [@"库大小\t库名称\r\n\r\n" mutableCopy];
    NSUInteger totalSize = 0;
    
    NSMutableDictionary *combinationMap = [[NSMutableDictionary alloc] init];
    
    for(ObjectResult *symbol in symbols) {
        NSString *name = [[symbol.file componentsSeparatedByString:@"/"] lastObject];
        if ([name hasSuffix:@")"] &&
            [name containsString:@"("]) {
            NSRange range = [name rangeOfString:@"("];
            NSString *component = [name substringToIndex:range.location];
            
            ObjectResult *combinationSymbol = [combinationMap objectForKey:component];
            if (!combinationSymbol) {
                combinationSymbol = [[ObjectResult alloc] init];
                [combinationMap setObject:combinationSymbol forKey:component];
            }
            
            combinationSymbol.size += symbol.size;
            combinationSymbol.file = component;
        } else {
            // symbol可能来自app本身的目标文件或者系统的动态库，在最后的结果中一起显示
            [combinationMap setObject:symbol forKey:symbol.file];
        }
    }
    
    NSArray <ObjectResult *>*combinationSymbols = [combinationMap allValues];
    
    NSArray *sortedSymbols = [SymbolUtils sortSymbols:combinationSymbols];
        
    for(ObjectResult *symbol in sortedSymbols) {
        if (searchKey.length > 0) {
            if ([symbol.file containsString:searchKey]) {
                [self appendResultWithSymbol:symbol result:result];
                totalSize += symbol.size;
            }
        } else {
            [self appendResultWithSymbol:symbol result:result];
            totalSize += symbol.size;
        }
    }
    
    [result appendFormat:@"\r\n总大小: %.2fM\r\n",(totalSize/1024.0/1024.0)];
    return result;
}

- (NSString *)buildModuleResultWithSymbols:(NSArray *)symbols searchKey:(NSString *)searchKey {
    NSMutableString *result = [@"库大小\t库名称\r\n\r\n" mutableCopy];
    NSUInteger totalSize = 0;
    
    NSMutableDictionary *combinationMap = [[NSMutableDictionary alloc] init];
    
    for(ObjectResult *symbol in symbols) {
        NSString *name = [[symbol.file componentsSeparatedByString:@"/"] lastObject];
        if ([name hasSuffix:@")"] &&
            [name containsString:@"("]) {
            NSRange range = [name rangeOfString:@"("];
            NSString *component = [name substringToIndex:range.location];
            
            ModuleResult *combinationSymbol = [combinationMap objectForKey:component];
            if (!combinationSymbol) {
                combinationSymbol = [[ModuleResult alloc] init];
                [combinationMap setObject:combinationSymbol forKey:component];
            }
            [combinationSymbol addObj:symbol];
            combinationSymbol.moduleName = component;
        } else {
            // symbol可能来自app本身的目标文件或者系统的动态库，在最后的结果中一起显示
            ModuleResult *combinationSymbol = [[ModuleResult alloc] init];
            [combinationSymbol addObj:symbol];
            combinationSymbol.moduleName = symbol.file;
            [combinationMap setObject:combinationSymbol forKey:combinationSymbol.moduleName];
        }
    }
    
    NSArray <ModuleResult *>*combinationSymbols = [combinationMap allValues];
    
    NSArray *sortedModules = [SymbolUtils sortModulesResults:combinationSymbols];
        
    for(ModuleResult *module in sortedModules) {
        totalSize += [self appendResultWithModuleResult:module result:result searchKey:searchKey];
    }
    
    [result appendFormat:@"\r\n总大小: %.2fM\r\n",(totalSize/1024.0/1024.0)];
    return result;
}

- (NSUInteger)appendResultWithModuleResult:(ModuleResult *)moduleResult result:(NSMutableString *)result searchKey:(NSString *)searchKey {
    if (searchKey && searchKey.length > 0 && ![moduleResult.moduleName containsString:searchKey]) {
        return 0;
    }
    
    [result appendFormat:@"%@\t%@\r\n",
     [self sizeStrWithSize:moduleResult.size],
     [moduleResult moduleName]];
    
    for (ObjectResult *object in moduleResult.objects) {
        [self appendResultWithSymbol:object result:result blankNum:4];
    }
    
    return moduleResult.size;
}

- (void)appendResultWithSymbol:(ObjectResult *)model result:(NSMutableString *)result {
    [self appendResultWithSymbol:model result:result blankNum:0];
}

- (void)appendResultWithSymbol:(ObjectResult *)model result:(NSMutableString *)result blankNum:(NSInteger)blankNum {
    [result appendFormat:@"%@%@\t%@\r\n",
     [self blankStrWithNum:blankNum],
     [self sizeStrWithSize:model.size],
     [[model.file componentsSeparatedByString:@"/"] lastObject]];
}

- (NSString *)blankStrWithNum:(NSInteger)num {
    static NSMutableDictionary *numToBlankStrMap = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        numToBlankStrMap = [NSMutableDictionary new];
    });
    NSString *existVal = numToBlankStrMap[@(num)];
    if (!existVal) {
        NSMutableString *blankStr = [NSMutableString new];
        NSInteger i = MIN(20, num);
        while (i > 0) {
            [blankStr appendString:@" "];
            i--;
        }
        existVal = numToBlankStrMap[@(num)] = blankStr;
    }
    return existVal;
}

- (NSString *)sizeStrWithSize:(NSInteger)size {
    NSString *sizeStr = nil;
    if (size / 1024.0 / 1024.0 > 1) {
        sizeStr = [NSString stringWithFormat:@"%.2fM", size / 1024.0 / 1024.0];
    } else {
        sizeStr = [NSString stringWithFormat:@"%.2fK", size / 1024.0];
    }
    return sizeStr;
}

@end
